.. _`F(x) List`: .. _`org.sysess.sympathy.data.generic.fxlist`: F(x) List ````````` .. image:: fx.svg :width: 48 Apply arbitrary python function(s) to each item of a List. Documentation ::::::::::::: The F(x) nodes have a similar role as the :ref:`Calculator` node. But where the :ref:`Calculator` node shines when the calculations are simple expressions, the F(x) nodes are better suited for more advanced calculations since the code may span multiple lines, include statements and may even be kept in an external python file. Defining a function =================== The python function that should be called by the node needs to be decorated with ``fx.decorator``. The function should also take exactly two positional arguments representing the input and output ports respectively. It is recommended to name the arguments ``arg`` and ``res``. These variables are of the same type as the input on port2. Consult the :ref:`API` for that type to figure out relevant operations. The argument to ``fx.decorator`` is a list of types (as shown in port tooltips) that you intend your script to support. Each decorated function is only available for use if the port type matches a listed type (e.g., `table` below). Example:: from sympathy.api import fx @fx.decorator(['table']) def my_calculation(arg, res): spam = arg['spam'] # My advanced calculation: more_spam = spam + 1 res['more spam'] = more_spam Script configuration ==================== The node has two different configuration modes which depend on the existence of the :ref:`optional input-port ` that provides a script file path. If the port exists, the script is kept in the `external` script file, otherwise it is kept `internal` in the node's configuration. Internal script mode is suitable for shorter scripts, and it executes all available functions. External script mode is suitable for longer scripts and scripts shared between different nodes, and it only executes selected functions (from all available). You can place the python file anywhere, but it might be a good idea to keep it in the same folder as your flow file or in a subfolder to that folder. A quick way to get the skeleton for a function script is to use the function wizard that is started by clicking *File->Wizards->New Function*. .. versionchanged:: 6.0.0 the optional input-port that provides the script path is no longer added to new nodes. Editor ====== The internal editor is a basic code editor which supports syntax highlighting and has basic support for indentation in python code, i.e. indentating using 4 spaces after pressing TAB and ENTER. It is included in Sympathy. Script files can be edited using either the `internal` or the `external` editor. The external editor is the global editor in Sympathy, it is normally the default program configured to open python files (.py) and only supports external script files. Debugging your functions ======================== When the functions are in an external file they can be debugged by following the normal process for debugging nodes. See :ref:`general_debug` for instructions. List behavior ============= The same function can be used with both :ref:`F(x)` and :ref:`F(x) List` nodes. For example a function specified to run for type 'table' can be used with an F(x) node connected to a single table or with an F(x) List node connected to a list of tables. In the latter case the function will be executed once per item in the list. Configuration ============= When *Copy input* is disabled (the default) the output data structure will be empty when the functions are run. When the *Copy input* setting is enabled the entire input data structure will get copied to the output before running the functions in the file. This is useful when your functions should only add some data to the input data. Alternative function definition =============================== Another syntax for writing a "function" is to define a class which inherits from ``fx.Fx``. The ``fx.Fx`` class provides access to the input and output with ``self.arg`` and ``self.res`` respectively. These variables are of the same type as the input on port2. The field ``arg_types`` should contain the list of types that you intend your script to support. Example:: from sympathy.api import fx class MyCalculation(fx.Fx): arg_types = ['table'] def execute(self): spam = self.arg['spam'] # My advanced calculation: more_spam = spam + 1 self.res['more spam'] = more_spam This syntax is available mostly for backwards compatibility. For new functions it is recommended to use the syntax with decorated functions. Definition :::::::::: Input ports =========== **port1** 0 - 1, datasource Path to Python file with scripted functions. **port2** [] List with data to apply functions on Output ports ============ **port3** [] List with function(s) applied Configuration ============= **Python code** (code) Python code block, input is called arg, output res. **Copy input** (copy_input) If enabled the incoming data will be copied to the output before running the nodes. **Select functions** (selected_functions) Choose one or many of the listed functions to apply to the content of the incoming item. Related nodes ============= * :ref:`org.sysess.sympathy.data.fx` Examples ======== * :download:`Functions.syx ` Implementation ============== .. automodule:: node_fx_selector :noindex: .. class:: FxList :noindex: